home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / cli / gulamdoc.arc / TEXINDEX.C < prev    next >
C/C++ Source or Header  |  1987-11-02  |  40KB  |  1,569 lines

  1. /* Prepare Tex index dribble output into an actual index.
  2.    Copyright (C) Richard M. Stallman 1984, 1987
  3.  
  4.    Permission is granted to anyone to make or distribute
  5.    verbatim copies of this program
  6.    provided that the copyright notice and this permission notice are preserved;
  7.    and provided that the recipient is not asked to waive or limit his right to
  8.    redistribute copies as permitted by this permission notice;
  9.    and provided that anyone possessing a machine-executable copy
  10.    is granted access to copy the source code, in machine-readable form,
  11.    in some reasonable manner.
  12.  
  13.    Permission is granted to distribute derived works or enhanced versions of
  14.    this program under the above conditions with the additional condition
  15.    that the entire derivative or enhanced work
  16.    must be covered by a permission notice identical to this one.
  17.  
  18.    Anything distributed as part of a package containing portions derived
  19.    from this program, which cannot in current practice perform its function
  20.    usefully in the absence of what was derived directly from this program,
  21.    is to be considered as forming, together with the latter,
  22.    a single work derived from this program,
  23.    which must be entirely covered by a permission notice identical to this one
  24.    in order for distribution of the package to be permitted.
  25.  
  26.  In other words, you are welcome to use, share and improve this program.
  27.  You are forbidden to forbid anyone else to use, share and improve
  28.  what you give them.   Help stamp out software-hoarding!  */
  29.  
  30. #include <stdio.h>
  31. #include <ctype.h>
  32.  
  33. #ifdef VMS
  34. #include <file.h>
  35.  
  36. #define EXIT_SUCCESS ((1 << 28) | 1)
  37. #define EXIT_FATAL ((1 << 28) | 4)
  38. #define unlink delete
  39. #define tell(fd) lseek(fd, 0L, 1)
  40. #else
  41. #include <sys/file.h>
  42.  
  43. #define EXIT_SUCCESS 0
  44. #define EXIT_FATAL 1
  45. #endif
  46.  
  47.  
  48. #ifndef L_XTND
  49. #define L_XTND 2
  50. #endif
  51.  
  52. /* When sorting in core, this structure describes one line
  53.  and the position and length of its first keyfield.  */
  54.  
  55. struct lineinfo
  56.   {
  57.     char *text;        /* The actual text of the line */
  58.     union
  59.       {            /* The start of the key (for textual comparison) */
  60.     char *text;
  61.     long number;    /* or the numeric value (for numeric comparison) */
  62.       } key;
  63.     long keylen;    /* Length of key field */
  64.   };
  65.  
  66. /* This structure describes a field to use as a sort key */
  67.  
  68. struct keyfield
  69.   {
  70.     int startwords;        /* # words to skip  */
  71.     int startchars;        /*  and # additional chars to skip, to start of field */
  72.     int endwords;        /* similar, from beg (or end) of line, to find end of field */
  73.     int endchars;
  74.     char ignore_blanks;        /* Ignore spaces and tabs within the field */
  75.     char fold_case;        /* Convert upper case to lower before comparing */
  76.     char reverse;        /* Compare in reverse order */
  77.     char numeric;        /* Parse text as an integer and compare the integers */
  78.     char positional;        /* Sort according to position within the file */
  79.     char braced;        /* Count balanced-braced groupings as fields */
  80.   };
  81.  
  82. /* Vector of keyfields to use */
  83.  
  84. struct keyfield keyfields[3];
  85.  
  86. /* Number of keyfields stored in that vector.  */
  87.  
  88. int num_keyfields = 3;
  89.  
  90. /* Vector of input file names, terminated with a zero (null pointer) */
  91.  
  92. char **infiles;
  93.  
  94. /* Vector of corresponding output file names, or zero meaning default it */
  95.  
  96. char **outfiles;
  97.  
  98. /* Length of `infiles' */
  99.  
  100. int num_infiles;
  101.  
  102. /* Pointer to the array of pointers to lines being sorted */
  103.  
  104. char **linearray;
  105.  
  106. /* The allocated length of `linearray'. */
  107.  
  108. long lines;
  109.  
  110. /* Directory to use for temporary files.  On Unix, it ends with a slash.  */
  111.  
  112. char *tempdir;
  113.  
  114. /* Start of filename to use for temporary files.  */
  115.  
  116. char *tempbase;
  117.  
  118. /* Number of last temporary file.  */
  119.  
  120. int tempcount;
  121.  
  122. /* Number of last temporary file already deleted.
  123.  Temporary files are deleted by `flush_tempfiles' in order of creation.  */
  124.  
  125. int last_deleted_tempcount;
  126.  
  127. /* During in-core sort, this points to the base of the data block
  128.  which contains all the lines of data.  */
  129.  
  130. char *text_base;
  131.  
  132. /* Additional command switches */
  133.  
  134. int keep_tempfiles;    /* Nonzero means do not delete tempfiles -- for debugging */
  135.  
  136. /* Forward declarations of functions in this file */
  137.  
  138. void decode_command ();
  139. void sort_in_core ();
  140. void sort_offline ();
  141. char **parsefile ();
  142. char *find_field ();
  143. char *find_pos ();
  144. long find_value ();
  145. char *find_braced_pos ();
  146. char *find_braced_end ();
  147. void writelines ();
  148. int compare_full ();
  149. long readline ();
  150. int merge_files ();
  151. int merge_direct ();
  152. char *concat ();
  153. char *maketempname ();
  154. void flush_tempfiles ();
  155. char *tempcopy ();
  156.  
  157. extern char *mktemp ();
  158.  
  159. #define MAX_IN_CORE_SORT 500000
  160.  
  161. int
  162. main (argc, argv)
  163.      int argc;
  164.      char **argv;
  165. {
  166.   int i;
  167.  
  168.   tempcount = 0;
  169.   last_deleted_tempcount = 0;
  170.  
  171.   /* Describe the kind of sorting to do. */
  172.   /* The first keyfield uses the first braced field and folds case */
  173.   keyfields[0].braced = 1;
  174.   keyfields[0].fold_case = 1;
  175.   keyfields[0].endwords = -1;
  176.   keyfields[0].endchars = -1;
  177.   /* The second keyfield uses the second braced field, numerically */
  178.   keyfields[1].braced = 1;
  179.   keyfields[1].numeric = 1;
  180.   keyfields[1].startwords = 1;
  181.   keyfields[1].endwords = -1;
  182.   keyfields[1].endchars = -1;
  183.   /* The third keyfield (which is ignored while discarding duplicates)
  184.      compares the whole line */
  185.   keyfields[2].endwords = -1;
  186.   keyfields[2].endchars = -1;
  187.  
  188.   decode_command (argc, argv);
  189.  
  190.   tempbase = mktemp (concat ("txiXXXXXX", "", ""));
  191.  
  192.   /* Process input files completely, one by one.  */
  193.  
  194.   for (i = 0; i < num_infiles; i++)
  195.     {
  196.       int desc;
  197.       long ptr;
  198.       char *outfile;
  199.       char *p;
  200.  
  201.       desc = open (infiles[i], 0, 0);
  202.       if (desc < 0) pfatal_with_name (infiles[i]);
  203.       lseek (desc, 0, L_XTND);
  204.       ptr = tell (desc);
  205.       close (desc);
  206.  
  207.       outfile = outfiles[i];
  208.       if (!outfile)
  209.     {
  210.       outfile = concat (infiles[i], "s", "");
  211.     }
  212.  
  213.       if (ptr < MAX_IN_CORE_SORT)
  214.         /* Sort a small amount of data */
  215.         sort_in_core (infiles[i], ptr, outfile);
  216.       else
  217.         sort_offline (infiles[i], ptr, outfile);
  218.     }
  219.  
  220.   flush_tempfiles (tempcount);
  221.   exit (EXIT_SUCCESS);
  222. }
  223.  
  224. /* This page decodes the command line arguments to set the parameter variables
  225.  and set up the vector of keyfields and the vector of input files */
  226.  
  227. void
  228. decode_command (argc, argv)
  229.      int argc;
  230.      char **argv;
  231. {
  232.   int i;
  233.   char **ip;
  234.   char **op;
  235.  
  236.   /* Store default values into parameter variables */
  237.  
  238. #ifdef VMS
  239.   tempdir = "sys$scratch:";
  240. #else
  241.   tempdir = "/tmp/";
  242. #endif
  243.  
  244.   keep_tempfiles = 0;
  245.  
  246.   /* Allocate argc input files, which must be enough.  */
  247.  
  248.   infiles = (char **) xmalloc (argc * sizeof (char *));
  249.   outfiles = (char **) xmalloc (argc * sizeof (char *));
  250.   ip = infiles;
  251.   op = outfiles;
  252.  
  253.   /* First find all switches that control the default kind-of-sort */
  254.  
  255.   for (i = 1; i < argc; i++)
  256.     {
  257.       int tem = classify_arg (argv[i]);
  258.       char c;
  259.       char *p;
  260.  
  261.       if (tem <= 0)
  262.     {
  263.       *ip++ = argv[i];
  264.       *op++ = 0;
  265.       continue;
  266.     }
  267.       if (tem > 1)
  268.     {
  269.       if (i + 1 == argc)
  270.         fatal ("switch %s given with no argument following it", argv[i]);
  271.       else if (!strcmp (argv[i], "-T"))
  272.         tempdir = argv[i + 1];
  273.       else if (!strcmp (argv[i], "-o"))
  274.         *(op - 1) = argv[i + 1];
  275.       i += tem - 1;
  276.       continue;
  277.     }
  278.  
  279.       p = &argv[i][1];
  280.       while (c = *p++)
  281.     switch (c)
  282.       {
  283.       case 'k':
  284.         keep_tempfiles = 1;
  285.         break;
  286.  
  287.       default:
  288.         fatal ("invalid command switch %c", c);
  289.       }
  290.     switchdone: ;
  291.     }
  292.  
  293.   /* Record number of keyfields, terminate list of filenames */
  294.  
  295.   num_infiles = ip - infiles;
  296.   *ip = 0;
  297. }
  298.  
  299. /* Return 0 for an argument that is not a switch;
  300.  for a switch, return 1 plus the number of following arguments that the switch swallows.
  301. */
  302.  
  303. int
  304. classify_arg (arg)
  305.      char *arg;
  306. {
  307.   if (!strcmp (arg, "-T") || !strcmp (arg, "-o"))
  308.     return 2;
  309.   if (arg[0] == '-')
  310.     return 1;
  311.   return 0;
  312. }
  313.  
  314. /* Create a name for a temporary file */
  315.  
  316. char *
  317. m